package org.xp.judgeplatform.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.xp.judgeplatform.service.LanguageExecutor;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component("python")  // 使用语言名称作为Bean名称
public class PythonExecutor implements LanguageExecutor {

    private static final String CONTAINER_NAME = "judge-platform-service-python";
    private static final String EXECUTE_COMMAND = "python /app/judge_runner.py";

    @Override
    public String getContainerName() {
        return CONTAINER_NAME;
    }

    @Override
    public String getExecuteCommand() {
        return EXECUTE_COMMAND;
    }

    @Override
    public String execute(String code, String testCasesJson, String functionName) throws Exception {
        // 检查容器是否运行
        if (!isContainerRunning()) {
            throw new RuntimeException("Python判题容器未运行，请检查Docker服务");
        }
        
        // 检查代码安全性（不安全则拒绝）
        if (!isCodeSafe(code)) {
            throw new SecurityException("代码包含不安全操作，已拒绝执行");
        }

        // 使用文件传递参数，避免命令行参数转义问题
        // 使用挂载的temp目录，与docker-compose.yml中的挂载路径一致
        String tempDir = "/app/temp/judge_" + System.currentTimeMillis();
        
        // 创建临时目录
        ProcessBuilder mkdirBuilder = new ProcessBuilder("docker", "exec", CONTAINER_NAME, "mkdir", "-p", tempDir);
        mkdirBuilder.start().waitFor();
        
        // 写入代码文件
        ProcessBuilder codeBuilder = new ProcessBuilder("docker", "exec", "-i", CONTAINER_NAME, "tee", tempDir + "/code.py");
        Process codeProcess = codeBuilder.start();
        codeProcess.getOutputStream().write(code.getBytes(StandardCharsets.UTF_8));
        codeProcess.getOutputStream().close();
        codeProcess.waitFor();
        
        // 写入测试用例文件
        ProcessBuilder testBuilder = new ProcessBuilder("docker", "exec", "-i", CONTAINER_NAME, "tee", tempDir + "/test_cases.json");
        Process testProcess = testBuilder.start();
        testProcess.getOutputStream().write(testCasesJson.getBytes(StandardCharsets.UTF_8));
        testProcess.getOutputStream().close();
        testProcess.waitFor();
        
        // 执行判题脚本
        String[] command = {
            "docker", "exec", CONTAINER_NAME, 
            "python", "/app/judge_runner_file.py",
            tempDir + "/code.py", tempDir + "/test_cases.json", functionName != null ? functionName : "solution"
        };

        log.info("执行Python判题，容器: {}, 函数: {}", CONTAINER_NAME, functionName);
        
        // 执行命令
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(false); // 分别处理标准输出和错误输出
        Process process = processBuilder.start();

        // 获取标准输出
        StringBuilder output = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line);
            }
        }

        // 获取错误输出
        StringBuilder errorOutput = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getErrorStream(), StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                errorOutput.append(line).append("\n");
            }
        }

        // 等待进程结束并检查退出码
        int exitCode = process.waitFor();
        
        // 清理临时文件
        try {
            ProcessBuilder cleanupBuilder = new ProcessBuilder("docker", "exec", CONTAINER_NAME, "rm", "-rf", tempDir);
            cleanupBuilder.start().waitFor();
        } catch (Exception e) {
            log.warn("清理临时文件失败: {}", e.getMessage());
        }
        
        if (exitCode != 0) {
            log.error("Python执行失败，退出码: {}, 错误信息: {}", exitCode, errorOutput);
            throw new RuntimeException("Python执行失败: " + errorOutput.toString().trim());
        }
        
        if (!errorOutput.isEmpty()) {
            log.warn("Python执行警告: {}", errorOutput);
        }

        String result = output.toString().trim();
        // DEBUG级别：Python执行的原始结果（用于调试判题逻辑）
        log.debug("Python执行结果: {}", result);
        return result;
    }

    @Override
    public boolean isCodeSafe(String code) {
        if (code == null || code.trim().isEmpty()) {
            return false; // 空代码也被认为是不安全的
        }
        
        try {
            // 基础危险关键词检查
            if (!basicSafetyCheck(code)) {
                return false;
            }
            
            // 高级语法模式检查
            if (!advancedPatternCheck(code)) {
                return false;
            }
            
            // 白名单语法检查
            if (!whitelistSyntaxCheck(code)) {
                return false;
            }
            
            // 代码复杂度检查
            if (!complexityCheck(code)) {
                return false;
            }

            // 编码和混淆检查
            return encodingObfuscationCheck(code);

        } catch (Exception e) {
            log.error("代码安全检查过程中发生异常", e);
            return false; // 异常情况下拒绝执行
        }
    }
    
    /**
     * 基础危险关键词检查
     */
    private boolean basicSafetyCheck(String code) {
        // 危险的导入模块
        String[] dangerousImports = {
            "import os", "import sys", "import subprocess", "import shutil",
            "import socket", "import urllib", "import requests", "import http",
            "import ftplib", "import smtplib", "import telnetlib", "import webbrowser",
            "import ctypes", "import platform", "import threading", "import multiprocessing",
            "import pickle", "import marshal", "import imp", "import importlib",
            "from os", "from sys", "from subprocess", "from shutil",
            "from socket", "from urllib", "from requests", "from http"
        };
        
        // 危险的函数调用
        // 注意：只禁止真正危险的操作（文件IO、网络、进程、系统调用）
        // 允许：chr, ord, print 等常用内置函数
        String[] dangerousFunctions = {
            "os.system(", "os.popen(", "os.exec", "os.spawn", "os.fork(",
            "subprocess.", "exec(", "eval(", "compile(", "__import__(",
            "open(", "file(",  // 文件操作
            "globals(", "locals(", "vars(", "dir(", 
            "getattr(", "setattr(", "delattr(", "hasattr(",
            "exit(", "quit(", "reload(", "help(",
            "memoryview(", "bytearray(", "bytes("
            // 已移除：chr, ord, print, input, raw_input
        };
        
        // 危险的内置属性和方法
        String[] dangerousBuiltins = {
            "__builtins__", "__file__", "__name__", "__doc__",
            "__dict__", "__class__", "__bases__", "__mro__",
            "__subclasses__", "__globals__", "__code__", "__closure__"
        };
        
        String lowerCode = code.toLowerCase();
        
        // 检查危险导入
        for (String dangerous : dangerousImports) {
            if (lowerCode.contains(dangerous.toLowerCase())) {
                log.warn("发现危险导入: {}", dangerous);
                return false;
            }
        }
        
        // 检查危险函数
        for (String dangerous : dangerousFunctions) {
            if (lowerCode.contains(dangerous.toLowerCase())) {
                log.warn("发现危险函数调用: {}", dangerous);
                return false;
            }
        }
        
        // 检查危险内置属性
        for (String dangerous : dangerousBuiltins) {
            if (lowerCode.contains(dangerous.toLowerCase())) {
                log.warn("发现危险内置属性访问: {}", dangerous);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 高级语法模式检查
     */
    private boolean advancedPatternCheck(String code) {
        // 危险的正则表达式模式
        String[] dangerousPatterns = {
            ".*\\.system\\s*\\(",  // .system() 调用
            ".*\\.popen\\s*\\(",   // .popen() 调用
            ".*exec\\s*\\(",       // exec() 调用
            ".*eval\\s*\\(",       // eval() 调用
            ".*__import__\\s*\\(", // __import__() 调用
            ".*\\bopen\\s*\\(",     // open() 文件操作
            ".*\\[.*\\]\\..*\\(",   // 可疑的属性访问模式
            ".*getattr\\s*\\(",    // getattr() 动态属性获取
            ".*setattr\\s*\\(",    // setattr() 动态属性设置
            ".*chr\\s*\\(.*\\).*join", // chr() + join() 编码绕过
            ".*\\\\x[0-9a-fA-F]{2}", // 十六进制编码
            ".*\\\\[0-7]{3}",      // 八进制编码
        };
        
        for (String pattern : dangerousPatterns) {
            if (code.matches("(?s)" + pattern)) { // (?s) 让 . 匹配换行符
                log.warn("发现危险语法模式: {}", pattern);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 白名单语法检查
     */
    private boolean whitelistSyntaxCheck(String code) {
        // 只允许的关键字（基础Python语法）
        String[] allowedKeywords = {
            "def", "class", "if", "else", "elif", "for", "while", "break", "continue",
            "return", "yield", "try", "except", "finally", "raise", "with", "as",
            "and", "or", "not", "in", "is", "True", "False", "None",
            "int", "float", "str", "list", "dict", "set", "tuple",
            "len", "range", "enumerate", "zip", "map", "filter", "sum", "max", "min",
            "sorted", "reversed", "print" // 允许print用于调试
        };
        
        // 移除字符串字面量和注释，避免误判
        String cleanCode = removeStringsAndComments(code);
        
        // 提取代码中使用的标识符
        String[] words = cleanCode.split("\\W+");
        
        for (String word : words) {
            if (word.isEmpty() || word.matches("\\d+")) { // 跳过空字符串和数字
                continue;
            }
            
            // 检查是否是自定义变量或函数名（简单的命名模式）
            if (word.matches("[a-zA-Z_][a-zA-Z0-9_]*")) {
                // 检查是否在允许列表中，或者是合理的变量命名
                boolean isAllowed = false;
                for (String allowed : allowedKeywords) {
                    if (word.equals(allowed)) {
                        isAllowed = true;
                        break;
                    }
                }
                
                // 允许合理的变量命名（不包含特殊字符）
                if (!isAllowed && !word.startsWith("_") && !word.contains("__")) {
                    // 这是用户定义的变量或函数，暂时允许
                    // 但需要进一步检查其使用方式
                    continue;
                }
                
                if (!isAllowed && (word.startsWith("_") || word.contains("__"))) {
                    log.warn("发现可疑的标识符: {}", word);
                    return false;
                }
            }
        }
        
        return true;
    }
    
    /**
     * 代码复杂度检查
     */
    private boolean complexityCheck(String code) {
        // 检查代码行数
        String[] lines = code.split("\\n");
        if (lines.length > 100) {
            log.warn("代码行数过多: {}", lines.length);
            return false;
        }
        
        // 检查嵌套层级
        int maxIndentLevel = 0;
        
        for (String line : lines) {
            String trimmed = line.trim();
            if (trimmed.isEmpty()) continue;
            
            // 计算缩进层级
            int indentLevel = (line.length() - line.replaceAll("^\\s+", "").length()) / 4;
            maxIndentLevel = Math.max(maxIndentLevel, indentLevel);
        }
        
        if (maxIndentLevel > 10) {
            log.warn("代码嵌套层级过深: {}", maxIndentLevel);
            return false;
        }
        
        // 检查单行长度
        for (String line : lines) {
            if (line.length() > 200) {
                log.warn("单行代码过长: {}", line.length());
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 编码和混淆检查
     */
    private boolean encodingObfuscationCheck(String code) {
        // 检查是否包含编码字符串
        if (code.contains("\\x") || code.contains("\\u") || code.contains("\\U")) {
            log.warn("发现编码字符串，可能用于绕过检查");
            return false;
        }
        
        // 检查是否有过多的特殊字符（可能是混淆代码）
        long specialCharCount = code.chars()
            .filter(ch -> !Character.isLetterOrDigit(ch) && !Character.isWhitespace(ch))
            .filter(ch -> ch != '(' && ch != ')' && ch != '[' && ch != ']' && 
                         ch != '{' && ch != '}' && ch != ',' && ch != ':' && 
                         ch != '.' && ch != '=' && ch != '+' && ch != '-' && 
                         ch != '*' && ch != '/' && ch != '%' && ch != '<' && 
                         ch != '>' && ch != '!' && ch != '?' && ch != ';')
            .count();
            
        if (specialCharCount > code.length() * 0.1) { // 特殊字符超过10%
            log.warn("代码包含过多特殊字符，疑似混淆: {}", specialCharCount);
            return false;
        }
        
        return true;
    }
    
    /**
     * 移除字符串字面量和注释
     */
    private String removeStringsAndComments(String code) {
        // 简单的字符串和注释移除（不是完美的解析，但足够用于安全检查）
        return code
            .replaceAll("\"\"\"[\\s\\S]*?\"\"\"", "") // 三引号字符串
            .replaceAll("'''[\\s\\S]*?'''", "")      // 三引号字符串
            .replaceAll("\"[^\"\\n]*\"", "")        // 双引号字符串
            .replaceAll("'[^'\\n]*'", "")          // 单引号字符串
            .replaceAll("#[^\\n]*", "");           // 单行注释
    }
    
    /**
     * 检查容器是否运行
     */
    private boolean isContainerRunning() {
        try {
            ProcessBuilder pb = new ProcessBuilder("docker", "inspect", "-f", "{{.State.Running}}", CONTAINER_NAME);
            Process process = pb.start();
            
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
                String result = reader.readLine();
                int exitCode = process.waitFor();
                
                return exitCode == 0 && "true".equals(result);
            }
        } catch (Exception e) {
            log.error("检查容器状态失败: {}", e.getMessage());
            return false;
        }
    }
}